"""
仿真类SUMO，定义仿真过程相关操作
"""
import os
import sys
import time
import traci
import traci.constants as tc
import config
import queuedata
import xml.etree.ElementTree as ET

from VirtualTrafficSystem.scenario.utils.commonUtils import sendRedis
from scenario.redis import connection


class SUMO:
    junctions = dict()  # 所有关注路口的Juntion对象

    def __init__(self, sumocfg):
        self.frame = 0
        # 设置sumocfg内容
        self.setSumocfg()
        self.inductionloopid = '##'
        # 更新根据加速倍数更新仿真步长
        traci.start(cmd=['sumo-gui', '--start', '-c', sumocfg, "--num-clients", "1", "--seed", "1"], port=8813)
        self.start = time.perf_counter()

    def subInductionloop(self, inductionloopid, radius):
        """
        订阅感应线圈数据（以检测器inductionloopid为中心，半径radius）
        """
        self.inductionloopid = inductionloopid
        # traci.inductionloop.subscribe(cjunctionid)
        traci.inductionloop.subscribeContext(
            inductionloopid, tc.CMD_GET_INDUCTIONLOOP_VARIABLE, radius, [tc.LAST_STEP_VEHICLE_NUMBER])
        #  检测器状态，key：16

    def setSumocfg(self):
        sumocfg_tree = ET.parse(config.sumoPath + config.sumoCfg)
        root = sumocfg_tree.getroot()
        # set input
        for item1 in root.findall('input'):
            for item11 in item1.findall('net-file'):
                item11.set('value', '%s' % (config.sumoNet))
            for item12 in item1.findall('route-files'):
                item12.set('value', '%s' % (config.sumoRou))
            for item13 in item1.findall('additional-files'):
                item13.set('value', '%s' % (config.sumoAdd))
        # set output
        for item2 in root.findall('output'):
            for item21 in item2.findall('tripinfo-output'):
                item21.set('value', '%sTrips.out.xml' % (config.outputName.split('.')[0]))
            for item22 in item2.findall('queue-output'):
                item22.set('value', '%sQueues.out.xml' % (config.outputName.split('.')[0]))
        # set step
        for item in root.findall('step-length'):
            item.set('value', '%s' % (config.steplength * config.multiple))
        tree = ET.ElementTree(root)
        tree.write(config.sumoPath + config.sumoCfg)

    def sumoRun(self, idSet, conn_road, msg_key):
        """仿真主循环"""
        m = 0
        while True:
            try:
                while traci.simulation.getMinExpectedNumber() > 0:
                    traci.simulationStep()
                    self.frame += 1
                    m += 1
                    if not self.inductionloopid == '##':
                        temp = traci.inductionloop.getContextSubscriptionResults(self.inductionloopid)
                        queuedata.det_queue.put(temp)
                    sendRedis(idSet, conn_road, msg_key)
                    q_size = queuedata.ryg_queue.qsize()
                    while q_size > 0:
                        tlsID, newryg = queuedata.ryg_queue.get()
                        traci.trafficlight.setRedYellowGreenState(tlsID, newryg)
                        traci.trafficlight.setPhaseDuration(tlsID, 999)
                        q_size -= 1
                    # 帧间休眠
                    sleeping = config.steplength * self.frame - (time.perf_counter() - self.start)
                    # print(sleeping)
                    if sleeping > 0:
                        time.sleep(sleeping)
                    if m == config.simulationDuration / (config.steplength * config.multiple):
                        traci.close()
                sys.stdout.flush()
            except Exception as e:
                print(e)

    def otherSumoRun(self):
        """仿真主循环"""
        m = 0
        while True:
            try:
                while traci.simulation.getMinExpectedNumber() > 0:
                    traci.simulationStep()
                    self.frame += 1
                    m += 1
                    if not self.inductionloopid == '##':
                        temp = traci.inductionloop.getContextSubscriptionResults(self.inductionloopid)
                        queuedata.det_queue.put(temp)
                    q_size = queuedata.ryg_queue.qsize()
                    while q_size > 0:
                        tlsID, newryg = queuedata.ryg_queue.get()
                        traci.trafficlight.setRedYellowGreenState(tlsID, newryg)
                        traci.trafficlight.setPhaseDuration(tlsID, 999)
                        q_size -= 1
                    # 帧间休眠
                    sleeping = config.steplength * self.frame - (time.perf_counter() - self.start)
                    # print(sleeping)
                    if sleeping > 0:
                        time.sleep(sleeping)
                    if m == config.simulationDuration / (config.steplength * config.multiple):
                        traci.close()
                sys.stdout.flush()
            except Exception as e:
                print(e)

    def simulation(self):
        current = os.getcwd()
        current = current.split("\\")[-1]
        if current == 'cvisRoad':
            print("cvis-road.hiacent.info")
            idSet = set()
            msg_key = 'exam_new:quene'
            conn_road = connection.connectRedis()
            self.sumoRun(idSet, conn_road, msg_key)
        elif current == 'demoRoad':
            print("demo-road.hiacent.info")
            idSet = set()
            msg_key = 'demo-road:quene'
            conn_road = connection.connectRedis()
            self.sumoRun(idSet, conn_road, msg_key)
        elif current == 'highTech1074':
            print("cvis.hiacent.info")
            idSet = set()
            msg_key = 'rsm:quene'
            conn_road = connection.connectRedis()
            self.sumoRun(idSet, conn_road, msg_key)
        else:
            self.otherSumoRun()
